﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PBLOG.Interfaces;
using System.Collections;
using PBLOG.Helpers;

namespace PBLOG.Collections
{
    public sealed class LogsCollection : ICollectionBase<Log>
    {        
        public IEnumerable<Log> Errors { get { return XmlHelper.Logs.List.Where(l => l.LogType == LogType.Error).AsEnumerable(); } }
        public IEnumerable<Log> Warnings { get { return XmlHelper.Logs.List.Where(l => l.LogType == LogType.Warning); } }
        public IEnumerable<Log> Informations { get { return XmlHelper.Logs.List.Where(l => l.LogType == LogType.Info); } }
        public IEnumerable<Log> Events { get { return XmlHelper.Logs.List.Where(l => l.LogType == LogType.Event); } }
        public IEnumerable<Log> Traces { get { return XmlHelper.Logs.List.Where(l => l.LogType == LogType.Trace); } }
        public IEnumerable<Log> Fatals { get { return XmlHelper.Logs.List.Where(l => l.LogType == LogType.Fatal); } }
        public IEnumerable<Log> Debugs { get { return XmlHelper.Logs.List.Where(l => l.LogType == LogType.Debug); } }

        public void Add(string message, LogType logType)
        {
            Log log = new Log()
            {
                Message = message,
                LogType = logType
            };            

            XmlHelper.Logs.WriteLog(log);
        }

        public void Add(string message, string username, LogType logType)
        {
            if (XmlHelper.Users.List.Count == 0)            
                throw new Exception("There aren't users");
            
            Utilities.ValidateUser(new User() { Username = username });

                Log log = new Log()
                {
                    Message = message,
                    LogType = logType,
                    User = XmlHelper.Users.List.Where(u => u.Username == username).SingleOrDefault()
                };

                XmlHelper.Logs.WriteLog(log);
        }

        public void Add(string message, User user, LogType logType)
        {
            Utilities.CheckUser(user);

            Log log = new Log()
            {
                Message = message,
                LogType = logType,
                User = user
            };            

            XmlHelper.Logs.WriteLog(log);
        }

        public void Add(Log item)
        {
            if (XmlHelper.Users.List.Count == 0)
                throw new Exception("There aren't users");

            XmlHelper.Logs.WriteLog(item);
        }

        public void Clear()
        {
            XmlHelper.Logs.List.Clear();

            XmlHelper.Logs.DeleteAllLogs();
        }

        public void Clear(LogType logType)
        {
            XmlHelper.Logs.List.RemoveAll(l => l.LogType == logType);

            XmlHelper.Logs.DeleteByType(logType);
        }

        public bool Exists(Predicate<Log> match)
        {
            return XmlHelper.Logs.List.Exists(match);
        }

        public bool Contains(string message, LogType logType)
        {
            return XmlHelper.Logs.List.Exists(l => l.Message == message && l.LogType == logType);
        }

        public bool Contains(string message, string username, LogType logType)
        {           
            return XmlHelper.Logs.List.Exists(l => l.Message == message && l.User.Username == username && l.LogType == logType);
        }

        public bool Contains(string message, User user, LogType logType)
        {
            Log log = new Log()
            {
                Message = message,
                LogType = logType,
                User = user
            };

            return this.CheckContains(log);
        }        

        public bool Contains(Log item)
        {
            return this.CheckContains(item);
        }

        public void CopyTo(Log[] array, int arrayIndex)
        {
            XmlHelper.Logs.List.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return XmlHelper.Logs.List.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(Log item)
        {   
         

            return XmlHelper.Logs.DeleteLog(item);
        }

        public IEnumerator<Log> GetEnumerator()
        {
            return XmlHelper.Logs.List.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return XmlHelper.Logs.List.GetEnumerator();
        }

        private bool CheckContains(Log item)
        {
            Predicate<Log> matchLog;

            if (String.IsNullOrWhiteSpace(item.Message))
                throw new ArgumentNullException("Message");

            else if (item.LogType == LogType.None)
                throw new ArgumentNullException("LogType");

            if (item.User != null)
            {
                if (!String.IsNullOrWhiteSpace(item.User.Rule))
                    matchLog = (Log l) => l.Message == item.Message &&
                        l.LogType == item.LogType &&
                        l.User.Username == item.User.Username &&
                        l.User.Rule == item.User.Rule;
                else
                    matchLog = (Log l) => l.Message == item.Message &&
                        l.LogType == item.LogType &&
                        l.User.Username == item.User.Username;
            }
            else
                matchLog = (Log l) => l.Message == item.Message &&
                        l.LogType == item.LogType;

            return XmlHelper.Logs.List.Exists(matchLog);
        }
    }
}